Skip to content

feat(rivetkit): trace actor to actor calls - #5732

Merged
NathanFlurry merged 11 commits into
stack/feat-rivetkit-core-trace-queue-sends-and-receives-wqpoztoqfrom
stack/feat-rivetkit-trace-actor-to-actor-calls-zosqvyzx
Sep 23, 2026
Merged

NathanFlurry merged 11 commits into
stack/feat-rivetkit-core-trace-queue-sends-and-receives-wqpoztoqfrom
stack/feat-rivetkit-trace-actor-to-actor-calls-zosqvyzx

Conversation

@eersnington

@eersnington eersnington commented Sep 15, 2026 •

Copy link
Copy Markdown
Member
  • Tracing HTTP action calls between actors, including routing, retries and wake time
  • Connecting both actors' work in the same trace
  • Testing that overlapping calls keep their traces and logs separate

@claude

claude Bot commented Sep 15, 2026 •

Copy link
Copy Markdown
Contributor

Review

Reviewed the current diff (traces actor-to-actor calls and workflow runs/steps via OpenTelemetry). This is a substantial, well-structured addition. The InvocationType-driven exhaustive matches, the finished-flag idempotency guards on span teardown, and the new sql_efficiency.rs coverage for workflow.kv_get are good signs of care. A few issues worth addressing:

Correctness

  1. ActorInvocationTelemetry::trace_context() ignores application_span (rivetkit-rust/packages/rivetkit-core/src/telemetry.rs:671)
    trace_context() only checks self.step_span, but parent_context() gives top precedence to self.application_span. Per the new docs (docs/content/docs/general/tracing.mdx, section "Add application spans"), code that wraps work in tracer.startActiveSpan("my-span", ...) expects c.log/ctx.invocationTraceContext() to report the my-span trace/span ID. Right now SQL calls correctly nest under the application span (via parent_context()), but logs and invocationTraceContext() still report the base invocation span IDs, inconsistent with the span the work actually nests under, and contradicting the example in the new docs.

  2. SDK warning can be silently dropped during a sink install/uninstall race (rivetkit-typescript/packages/rivetkit-napi/src/telemetry.rs:64 and :104-124)
    delivered_to_sink (read by the log layer filter) and SdkLogLayer::on_event (the forwarding path) independently read the same SINK: RwLock<Option<Sink>> at two different points in dispatch, with no lock held across both checks. If shutdownTelemetry() / setTelemetryLogSink() flips the sink between these two reads (plausible since it races background export/shutdown warnings emitted by the OTel SDK itself), the log layer can skip printing (assuming the sink will handle it) while the sink layer also skips forwarding (sink now gone), losing the warning entirely. This contradicts the claim in docs-internal/engine/rivetkit-telemetry.md that "each warning is visible once."

Performance

  1. Workflow-trace SQLite read gated on tracing::enabled!, not on whether an exporter is actually attached (rivetkit-rust/packages/rivetkit-core/src/actor/context.rs:312)
    start_workflow_span gates an extra _rivet_wf_kv SQLite read behind tracing::enabled!(target: "rivetkit::telemetry", INFO). This is correct today only because rivetkit-napi lib.rs explicitly appends rivetkit::telemetry=off to its log-layer filter. Any other host that installs a plain tracing_subscriber at INFO (a bare rivetkit Rust consumer, a test harness, a future runtime) would make this check return true unconditionally, silently paying the extra SQLite read on every workflow run with no OTLP exporter ever attached, and no diagnostic surfaced. Worth gating on an explicit exporter-configured check instead of subscriber interest.

Code quality (minor)

  1. Three Drop impls in telemetry.rs (OutboundCallInvocation ~855, WorkflowStepSpan ~891, SqliteOperationSpan ~914) duplicate the identical "record abandoned" body (otel.status_code = ERROR, error.type = OPERATION_ABANDONED_ERROR_TYPE). Consider a shared record_abandoned(&Span) helper alongside the existing record_outcome.
  2. anyhow_error_from_js_reason (rivetkit-typescript/packages/rivetkit-napi/src/actor_factory.rs:987) duplicates the first half of callback_error error-reconstruction logic (parse_bridge_rivet_error(...).unwrap_or_else(...)). A future change to the fallback rule risks being applied to only one copy.
  3. takes_message_ray (telemetry.rs:157 / ~590) is a one-off matches!(invocation_type, InvocationType::Workflow) rather than an exhaustive match like the rest of the file InvocationType-driven decisions (record_attributes, otel_kind). A new InvocationType variant that should also adopt an incoming message ray would silently default to false with no compiler signal. (This behavior is called out as intentional in the docs, so it is a mechanism nit, not a correctness bug.)

Test coverage

Test coverage looks solid: tests/driver/actor-telemetry.test.ts covers overlapping-call trace isolation, and sql_efficiency.rs was updated for the new query. It would be worth adding a regression test for finding #1 (application span vs. log / invocationTraceContext() correlation) since it is directly demonstrated in the new docs example.

Conventions

Checked against CLAUDE.md: vbare usage for the new WorkflowTraceContext mirrors the existing RunWakeAt pattern correctly, enum matches are exhaustive with no _ => fallbacks, structured logging fields are used correctly in the two new tracing::warn! calls, and the new parking_lot usages are in forced-sync contexts (NAPI on_event, &self methods) per the Async Rust Locks rule. No violations found there.

🤖 Generated with Claude Code

@eersnington
eersnington force-pushed the stack/feat-rivetkit-trace-actor-to-actor-calls-zosqvyzx branch from bc77372 to 384b32b Compare September 16, 2026 01:18

@the-company-company the-company-company Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟠 2 medium-severity findings

Reviewed commit 384b32b.


🟠 Medium · Keep outbound call tracing available on wasm

Every client created inside a wasm-hosted actor now receives beginOutboundCall, but this adapter always returns undefined. Its action calls therefore continue to propagate the invocation context directly and never emit the new client span, unlike the NAPI runtime.

Expose the core context operation through the wasm binding and forward it here (including its span and finish), rather than using this placeholder, so the portable CoreRuntime contract has the same tracing behavior on both runtimes.

Original location: "rivetkit-typescript/packages/rivetkit/src/registry/wasm-runtime.ts":550 (new side, not submitted inline).

Comment thread rivetkit-typescript/packages/rivetkit/src/client/actor-handle.ts
@eersnington
eersnington force-pushed the stack/feat-rivetkit-trace-actor-to-actor-calls-zosqvyzx branch from 384b32b to 7f1d947 Compare September 16, 2026 17:51

@the-company-company the-company-company Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟠 2 medium-severity findings

Reviewed commit 7f1d947.

Comment thread rivetkit-typescript/packages/rivetkit/src/registry/wasm-runtime.ts
Comment thread rivetkit-typescript/packages/rivetkit/src/client/actor-handle.ts
@eersnington
eersnington force-pushed the stack/feat-rivetkit-trace-actor-to-actor-calls-zosqvyzx branch from 7f1d947 to 41a28e0 Compare September 16, 2026 18:08

@the-company-company the-company-company Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟠 2 medium-severity findings

Reviewed commit 41a28e0.

Comment thread rivetkit-typescript/packages/rivetkit/src/registry/wasm-runtime.ts
Comment thread rivetkit-typescript/packages/rivetkit/src/client/actor-handle.ts
@eersnington
eersnington force-pushed the stack/feat-rivetkit-trace-actor-to-actor-calls-zosqvyzx branch from 41a28e0 to 945ecce Compare September 16, 2026 18:16

@the-company-company the-company-company Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟠 2 medium-severity findings

Reviewed commit 945ecce.

Comment thread rivetkit-typescript/packages/rivetkit/src/registry/wasm-runtime.ts
Comment thread rivetkit-typescript/packages/rivetkit/src/client/actor-handle.ts
Comment thread rivetkit-typescript/packages/rivetkit/src/client/actor-handle.ts
Comment thread rivetkit-rust/packages/rivetkit-core/src/telemetry.rs

@the-company-company the-company-company Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟠 2 medium-severity findings

Reviewed commit ae9c32e.

Comment thread rivetkit-typescript/packages/rivetkit/src/registry/wasm-runtime.ts
Comment thread rivetkit-typescript/packages/rivetkit/src/client/actor-handle.ts
@eersnington
eersnington force-pushed the stack/feat-rivetkit-trace-actor-to-actor-calls-zosqvyzx branch from ae9c32e to 241f2c1 Compare September 16, 2026 20:28

@the-company-company the-company-company Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟠 2 medium-severity findings

Reviewed commit 241f2c1.

Comment thread rivetkit-typescript/packages/rivetkit/src/registry/wasm-runtime.ts
Comment thread rivetkit-typescript/packages/rivetkit/src/client/actor-handle.ts
@eersnington
eersnington added this pull request to stack #5746 September 17, 2026 08:36
@eersnington
eersnington force-pushed the stack/feat-rivetkit-trace-actor-to-actor-calls-zosqvyzx branch from 241f2c1 to 9d7ac37 Compare September 17, 2026 15:14

@the-company-company the-company-company Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟠 2 medium-severity findings

Reviewed commit 9d7ac37.

Comment on lines +555 to +560
_actorName: string,
_actionName: string,
): RuntimeOutboundCall | undefined {
return undefined;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟠 Medium · Keep outbound call tracing available on wasm

Every actor client now receives beginOutboundCall, but this adapter always returns undefined. Actions issued by wasm-hosted actors therefore still propagate the invocation span directly and never emit the new client span, unlike the NAPI runtime.

Forward the core context operation through the wasm binding (including its span context and finish operation) rather than returning this placeholder so the portable CoreRuntime contract has matching tracing behavior.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nope. out of scope

Comment thread rivetkit-typescript/packages/rivetkit/src/client/actor-handle.ts
@eersnington
eersnington force-pushed the stack/feat-rivetkit-trace-actor-to-actor-calls-zosqvyzx branch from 9d7ac37 to aeeb217 Compare September 18, 2026 22:40

@the-company-company the-company-company Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ No issues found

Reviewed commit aeeb217.

@eersnington
eersnington force-pushed the stack/feat-rivetkit-trace-actor-to-actor-calls-zosqvyzx branch from aeeb217 to e143d11 Compare September 19, 2026 01:01
@eersnington
eersnington force-pushed the stack/feat-rivetkit-trace-actor-to-actor-calls-zosqvyzx branch from e143d11 to 6f7295c Compare September 21, 2026 22:56
@eersnington
eersnington force-pushed the stack/feat-rivetkit-trace-actor-to-actor-calls-zosqvyzx branch from 6f7295c to b965bf6 Compare September 22, 2026 15:28
feat(rivetkit): otel trace workflow runs and steps
…-tracing-docs-mqqwnuwl

docs(rivetkit): add actor tracing docs
…tel-sdk-warnings-to-the-pino-logger-vmosovzz

feat(rivetkit): forward otel sdk warnings to the pino logger

@NathanFlurry NathanFlurry left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed as part of the tracing stack.

@NathanFlurry
NathanFlurry merged commit 1619f25 into main Sep 23, 2026
7 of 11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants